﻿#region Using Statements
using Microsoft.Xna.Framework;
#endregion

namespace StarFox.ScreenComponents
{
    /// <summary>
    /// Implementation of an asteroid.
    /// </summary>
    public class Asteroid : IAsteroid
    {
        #region Constants

        // scale
        const float MinSize = 0.5f;
        const float MaxSize = 1.0f;

        // rotation velocity
        const float MinRotation = -MathHelper.Pi * 0.005f;
        const float MaxRotation = MathHelper.Pi * 0.005f;

        // movement velocity
        const float MinVelocity = 0.0f;
        const float MaxVelocity = 1.0f;

        #endregion

        #region Fields

        Vector3 position;
        Vector3 movement;
        float scale;
        Vector3 rotation;
        Vector2 rotVel;
        Matrix world;

        #endregion

        #region Properties

        /// <summary>
        /// Gets the model index used to draw the asteroid.
        /// </summary>
        public int Index { get; private set; }

        /// <summary>
        /// Gets or sets the position of the asteroid.
        /// </summary>
        public Vector3 Position
        {
            get { return position; }
            set
            {
                position = value;
                world.Translation = position;
            }
        }

        /// <summary>
        /// Gets or sets the movement direction and velocity of the asteroid.
        /// </summary>
        public Vector3 Movement
        {
            get { return movement; }
            set { movement = value; }
        }

        /// <summary>
        /// Gets the world matrix used to draw the asteroid.
        /// </summary>
        public Matrix World
        {
            get { return world; }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="index">The model index used to draw the asteroid.</param>
        /// <param name="position">The position of the asteroid.</param>
        /// <param name="shipPos">The position of the starship.</param>
        public Asteroid(int index, Vector3 position, Vector3 shipPos)
        {
            Index = index;
            this.position = position;

            scale = StarFoxHelper.RandomFloat(MinSize, MaxSize);

            rotation = new Vector3(StarFoxHelper.RandomFloat(-MathHelper.Pi, MathHelper.Pi),
                                   StarFoxHelper.RandomFloat(-MathHelper.Pi, MathHelper.Pi),
                                   StarFoxHelper.RandomFloat(-MathHelper.Pi, MathHelper.Pi));

            rotVel = new Vector2(StarFoxHelper.RandomFloat(MinRotation, MaxRotation),
                                 StarFoxHelper.RandomFloat(MinRotation, MaxRotation));

            movement.X = (position.X < shipPos.X) ? StarFoxHelper.RandomFloat(0.0f, 1.0f) : StarFoxHelper.RandomFloat(-1.0f, 0.0f);
            movement.Y = (position.Y < shipPos.Y) ? StarFoxHelper.RandomFloat(0.0f, 0.5f) : StarFoxHelper.RandomFloat(-0.5f, 0.0f);
            movement.Z = StarFoxHelper.RandomFloat(-1.0f, 1.0f);
            movement.Normalize();
            movement *= StarFoxHelper.RandomFloat(MinVelocity, MaxVelocity);
        }

        #endregion

        #region Update

        /// <summary>
        /// Called when the asteroid needs to be updated.
        /// </summary>
        public void Update()
        {
            world = Matrix.Identity;

            // adjust rotation
            rotation.X += rotVel.X;
            rotation.Y += rotVel.Y;
            world *= Matrix.CreateRotationX(rotation.X);
            world *= Matrix.CreateRotationY(rotation.Y);
            world *= Matrix.CreateRotationZ(rotation.Z);

            // adjust scale
            world.Right *= scale;
            world.Up *= scale;
            world.Backward *= scale;

            // adjust translation
            position += movement;
            world.Translation = position;
        }

        #endregion
    }
}
